module efso_utils_mod

  use flogger
  use const_mod
  use namelist_mod

  implicit none

contains

  function ind(x, x0) result(res)

    real(r8), intent(in) :: x(:)
    real(r8), intent(in) :: x0
    integer res(2)

    integer i

    res = -999
    if (x(1) < x(2)) then
      do i = 1, size(x) - 1
        if (x(i) <= x0 .and. x0 < x(i+1)) then
          res(1) = i
          res(2) = i + 1
          return
        end if
      end do
    else if (x(1) > x(2)) then
      do i = 1, size(x) - 1
        if (x(i) >= x0 .and. x0 > x(i+1)) then
          res(1) = i
          res(2) = i + 1
          return
        end if
      end do
    else
      print *, x
      call log_error('ind: Input array is not monotonic increasing or decreasing!', __FILE__, __LINE__)
    end if

  end function ind

  subroutine round_robin(num, parts, loc, ibeg, iend)

    integer, intent(in) :: num
    integer, intent(in) :: parts
    integer, intent(in) :: loc
    integer, intent(inout) :: ibeg
    integer, intent(inout) :: iend

    integer res_num, tmp_num, i

    res_num = mod(num, parts)
    do i = 0, loc - 1
      if (res_num /= 0 .and. i < res_num) then
        tmp_num = num / parts + 1
      else
        tmp_num = num / parts
      end if
      ibeg = ibeg + tmp_num
    end do
    if (res_num /= 0 .and. loc < res_num) then
      tmp_num = num / parts + 1
    else
      tmp_num = num / parts
    end if
    iend = ibeg + tmp_num - 1

  end subroutine round_robin

  subroutine check_omb_ua(omb, mask)

    real, intent(in) :: omb
    integer, intent(inout) :: mask

    if (omb_ua_limit /= inf .and. abs(omb) > omb_ua_limit) mask = 0

  end subroutine check_omb_ua

  subroutine check_omb_va(omb, mask)

    real, intent(in) :: omb
    integer, intent(inout) :: mask

    if (omb_va_limit /= inf .and. abs(omb) > omb_va_limit) mask = 0

  end subroutine check_omb_va

  subroutine check_omb_ta(omb, mask)

    real, intent(in) :: omb
    integer, intent(inout) :: mask

    if (omb_ta_limit /= inf .and. abs(omb) > omb_ta_limit) mask = 0

  end subroutine check_omb_ta

  subroutine check_omb_p(omb, mask)

    real, intent(in) :: omb
    integer, intent(inout) :: mask

    if (omb_p_limit /= inf .and. abs(omb) > omb_p_limit) mask = 0

  end subroutine check_omb_p

  subroutine check_omb_sh(omb, mask)

    real, intent(in) :: omb
    integer, intent(inout) :: mask

    if (omb_sh_limit /= inf .and. abs(omb) > omb_sh_limit) mask = 0

  end subroutine check_omb_sh

end module efso_utils_mod
